実例から学ぶ!AWSを活用したシステム開発の勘所 #devio2022
MADグループ@大阪の岩田です。Developers.IO 2022 〜技術で心を揺さぶる3日間〜 にて「実例から学ぶ!AWSを活用したシステム開発の勘所」というテーマでお話ししましたので、内容を簡単にご紹介します。
動画
スライド
内容
私が参加したとあるシステム開発プロジェクトを題材に、プロジェクト進行過程で発生した技術的なハマりごとや問題点、それに対する解決のアプローチをTIPS的に紹介する。という内容です。それぞれのトピック同士にはほぼ関連性がありません。
案件概要
この案件はSaaSアプリケーションのバックエンドAPI 開発案件でした。API GatewayとLambdaという定番の構成に加え、データストアにはRDS、RDS Proxyという構成です。
その他関連する技術としては以下の技術を利用しています。
- 言語…TypeScript
- ORM…TypeORM
- IaC、デプロイ… CDK
API仕様書の肥大化
OASの仕様に基づいてAPI仕様書を作成していましたが、YAMLファイルが1万行超えの規模になり、保守性に懸念がありました。そこでYAMLファイルを分割することで保守性を担保できるようにしました。
ポイントとして、親ファイル・子ファイル共にOASとして妥当な形式にすることで子ファイル単体でのプレビュー表示が可能となり、トライ&エラーのサイクルを早く回すことができます。
デプロイ速度の問題
元々Lambda Layersは利用せず、node_modulesもまとめて1つのファイルにバンドルしてデプロイパッケージを作成していましたが、バンドル処理やAssetのアップロード処理に長い時間がかかるようになってきました。そこでnode_modulesをLambda Layersに切り出すことでバンドル処理やAssetのアップロード処理の最適化を図りました。
Lambda Layersをデプロイする際は、node_modulesをバンドルする処理の中で不要なファイルを削除することで、Layerのスリム化を行っています。
また、package-lock.jsonやyarn.lockに変更が無い限りLayersを再ビルド&デプロイしないように制御するのもポイントです。
RDS Proxyのピン留め問題
このプロジェクトではTypeORMを利用していましたが、何も意識せずに普通にTypeORMを利用すると、Prepared StatementによってRDS Proxyのピン留めが引き起こされてしまいます。
Prepared Statementを利用しないようにWHERE句を自前で組み立てることでピン留めを回避しましたが、SQLインジェクションのリスクを考えると本来あまりやりたくない対応ではあります。。。
ピン留めの何が問題なのかをしっかりと考え
- ピン留めが許容できる処理についてはピン留めを許容する
- 必要に応じてhandler内でRDS Proxyと接続/切断する実装に切り替える
といった選択肢も考慮に入れるのが良いでしょう。
ピン留めについてはこちらのブログも参考にしてください
X-Rayの導入
各処理のトレーサビリティを向上させるためにX-Rayを導入したという話です。X-Rayは便利です。
なお、Error: Failed to get the current sub/segment from the context.
というエラーの対策にはsetContextMissingStrategy
でLOG_ERROR
を設定するよう紹介している情報が多いですが、どこかのバージョンからIGNORE_ERROR
というオプションが指定できるようになっています。ユニットテスト時はIGNORE_ERROR
を設定するのが良いでしょう。
ENIのDNSスロットリング問題
SecretsManagerへの過剰なアクセスによりENIのDNSスロットリングが発生したという問題です。こちらは適切なキャッシュロジックを組み込むことで回避しています。
ENIはサブネットとセキュリティグループの組み合わせごとに作成されるので、もしアプリにチューニングの余地が無いようならダミーのセキュリティグループを紐付けることでENIを追加作成するというアプローチも有効かもしれません。もっとも、ENIのDNSスロットリングが発生してしまうようなワークロードであればLambdaの利用自体を見直した方が良いかもしれませんが...
ログ出力の改善
テキスト形式のログをJSON形式の構造化ログに変更することで検索性を改善したという話です。
構造化ログのフォーマットについては以下のポリシーで設計しました。
- システム全体を通して重要な意味を持つ項目を最上位のキーに
- 外部APIのキー項目、DBキー項目、APIのパスパラメータ等
- 一部の処理においてのみ重要な情報はcontextというキー配下に
- contextはObject型とすることでログ出力側にも自由度を持たせつつ型定義を簡潔にする
まとめ
実際に開発案件を進めていくと様々な技術的問題が発生します。今回題材にしたプロジェクトではここでは紹介しきれなかった様々な問題が発生し、その都度対処を行ってきました。これらの課題は、開発の初期段階で「よくあるハマりごと」として認識することができれば、あまり時間をかけずに潰しこむことができる問題ばかりです。
この動画を見て頂いた方々が我々の経験を参考に効率よく開発案件を進められるようになれば幸いです。